{
 "cells": [
  {
   "cell_type": "raw",
   "metadata": {
    "raw_mimetype": "text/restructuredtext"
   },
   "source": [
    ".. _nb_checkpoint:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Checkpoints"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sometimes, it might be useful to store some checkpoints while executing an algorithm. In particular, if a run is very time-consuming. \n",
    "**pymoo** offers to resume a run by serializing the algorithm object and loading it. Resuming runs from checkpoints is possible \n",
    "\n",
    "- the functional way by calling the `minimize` method, \n",
    "- the object-oriented way by repeatedly calling the `next()` method or \n",
    "- from a text file ([Biased Initialization](../customization/initialization.ipynb) from `Population` )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Functional"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "============================================================\n",
      "n_gen |  n_eval |     igd      |      gd      |      hv     \n",
      "============================================================\n",
      "    1 |     100 |  0.591406724 |  2.857718076 |  0.084181986\n",
      "    2 |     200 |  0.439419904 |  2.804026496 |  0.155903707\n",
      "    3 |     300 |  0.439419904 |  1.872462802 |  0.155903707\n",
      "    4 |     400 |  0.406628182 |  1.691762017 |  0.171264712\n",
      "    5 |     500 |  0.346478785 |  1.554097169 |  0.232891285\n",
      "Loaded Checkpoint: <pymoo.algorithms.nsga2.NSGA2 object at 0x7fc4a3c44ed0>\n",
      "    6 |     600 |  0.260455007 |  1.253989046 |  0.265093318\n",
      "    7 |     700 |  0.222821654 |  0.717126159 |  0.347501941\n",
      "    8 |     800 |  0.203582202 |  0.391439629 |  0.375532991\n",
      "    9 |     900 |  0.186117820 |  0.369671935 |  0.403788724\n",
      "   10 |    1000 |  0.151651385 |  0.224374761 |  0.428602488\n",
      "   11 |    1100 |  0.138821144 |  0.222776811 |  0.452520064\n",
      "   12 |    1200 |  0.110953674 |  0.192121107 |  0.487726964\n",
      "   13 |    1300 |  0.091142642 |  0.138930760 |  0.521068931\n",
      "   14 |    1400 |  0.076385894 |  0.101588370 |  0.538341984\n",
      "   15 |    1500 |  0.065724984 |  0.085599120 |  0.556340204\n",
      "   16 |    1600 |  0.052312985 |  0.073323910 |  0.580538446\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   17 |    1700 |  0.040157888 |  0.057590782 |  0.598526672\n",
      "   18 |    1800 |  0.033648449 |  0.046445845 |  0.609433690\n",
      "   19 |    1900 |  0.025987575 |  0.042402381 |  0.621694736\n",
      "   20 |    2000 |  0.023786958 |  0.037166445 |  0.625944818\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "from pymoo.algorithms.nsga2 import NSGA2\n",
    "from pymoo.factory import get_problem\n",
    "from pymoo.optimize import minimize\n",
    "\n",
    "problem = get_problem(\"zdt1\", n_var=5)\n",
    "\n",
    "algorithm = NSGA2(pop_size=100)\n",
    "\n",
    "res = minimize(problem,\n",
    "               algorithm,\n",
    "               ('n_gen', 5),\n",
    "               seed=1,\n",
    "               copy_algorithm=False,\n",
    "               verbose=True)\n",
    "\n",
    "np.save(\"checkpoint\", algorithm)\n",
    "\n",
    "checkpoint, = np.load(\"checkpoint.npy\", allow_pickle=True).flatten()\n",
    "print(\"Loaded Checkpoint:\", checkpoint)\n",
    "\n",
    "# only necessary if for the checkpoint the termination criterion has been met\n",
    "checkpoint.has_terminated = False\n",
    "\n",
    "res = minimize(problem,\n",
    "               checkpoint,\n",
    "               ('n_gen', 20),\n",
    "               seed=1,\n",
    "               copy_algorithm=False,\n",
    "               verbose=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Object Oriented"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "Loaded Checkpoint: <pymoo.algorithms.nsga2.NSGA2 object at 0x7fc4a3cd6bd0>\n",
      "6\n",
      "7\n",
      "8\n",
      "9\n",
      "10\n",
      "11\n",
      "12\n",
      "13\n",
      "14\n",
      "15\n",
      "16\n",
      "17\n",
      "18\n",
      "19\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "20\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "from pymoo.algorithms.nsga2 import NSGA2\n",
    "from pymoo.factory import get_problem\n",
    "from pymoo.factory import get_termination\n",
    "from pymoo.optimize import minimize\n",
    "from pymoo.visualization.scatter import Scatter\n",
    "\n",
    "problem = get_problem(\"zdt1\", n_var=5)\n",
    "\n",
    "algorithm = NSGA2(pop_size=100)\n",
    "\n",
    "algorithm.setup(problem, seed=1, termination=('n_gen', 20))\n",
    "\n",
    "for k in range(5):\n",
    "    algorithm.next()\n",
    "    print(algorithm.n_gen)\n",
    "\n",
    "np.save(\"checkpoint\", algorithm)\n",
    "\n",
    "checkpoint, = np.load(\"checkpoint.npy\", allow_pickle=True).flatten()\n",
    "print(\"Loaded Checkpoint:\", checkpoint)\n",
    "\n",
    "while checkpoint.has_next():\n",
    "    checkpoint.next()\n",
    "    print(checkpoint.n_gen)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## From a Text File"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, load the data from a file. Usually, this will include the variables `X`, the objective values `F` (and the constraints `G`). Here, they are created randomly. Always make sure the `Problem` you are solving would return the same values for the given `X` values. Otherwise the data might be misleading for the algorithm.\n",
    "\n",
    "(This is not the case here. It is really JUST for illustration purposes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from pymoo.factory import G1\n",
    "\n",
    "problem = G1()\n",
    "\n",
    "N = 300\n",
    "np.random.seed(1)\n",
    "X = np.random.random((N, problem.n_var))\n",
    "\n",
    "# here F and G is re-evaluated - in practice you want to load them from files too\n",
    "F, G = problem.evaluate(X, return_values_of=[\"F\", \"G\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then, create a population object using your data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pymoo.model.evaluator import Evaluator\n",
    "from pymoo.model.population import Population\n",
    "from pymoo.model.problem import StaticProblem\n",
    "\n",
    "# now the population object with all its attributes is created (CV, feasible, ...)\n",
    "pop = Population.new(\"X\", X)\n",
    "pop = Evaluator().eval(StaticProblem(problem, F=F, G=G), pop)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And finally run it with a non-random initial population `sampling=pop`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "===========================================================================\n",
      "n_gen |  n_eval |   cv (min)   |   cv (avg)   |     fopt     |     favg    \n",
      "===========================================================================\n",
      "    1 |       0 |  0.00000E+00 |  0.119240090 | -3.86901E+00 | -1.03797E+00\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    2 |     100 |  0.00000E+00 |  0.00000E+00 | -3.86901E+00 | -2.31220E+00\n",
      "    3 |     200 |  0.00000E+00 |  0.00000E+00 | -4.27665E+00 | -2.89221E+00\n",
      "    4 |     300 |  0.00000E+00 |  0.00000E+00 | -5.00346E+00 | -3.40624E+00\n",
      "    5 |     400 |  0.00000E+00 |  0.00000E+00 | -5.00346E+00 | -3.92666E+00\n",
      "    6 |     500 |  0.00000E+00 |  0.00000E+00 | -5.65720E+00 | -4.35164E+00\n",
      "    7 |     600 |  0.00000E+00 |  0.00000E+00 | -6.84665E+00 | -4.73558E+00\n",
      "    8 |     700 |  0.00000E+00 |  0.00000E+00 | -6.84665E+00 | -5.11420E+00\n",
      "    9 |     800 |  0.00000E+00 |  0.00000E+00 | -6.84665E+00 | -5.51104E+00\n",
      "   10 |     900 |  0.00000E+00 |  0.00000E+00 | -6.96689E+00 | -5.83190E+00\n"
     ]
    }
   ],
   "source": [
    "from pymoo.algorithms.so_genetic_algorithm import GA\n",
    "from pymoo.optimize import minimize\n",
    "\n",
    "# the algorithm is now called with the population - biased initialization\n",
    "algorithm = GA(pop_size=100, sampling=pop)\n",
    "\n",
    "res = minimize(problem,\n",
    "               algorithm,\n",
    "               ('n_gen', 10),\n",
    "               seed=1,\n",
    "               verbose=True)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
